import { useAppStore } from '@/stores/app'
import dayjs from 'dayjs'
import { decode } from 'js-base64'
import { type DetailedError, Upload } from 'tus-js-client'
export type uploadConf = {
  endpoint: string
  file: File
  afterSuccess: (...args: any[]) => void
  afterError: (...args: any[]) => void
}
export default function useUpload() {
  const appStore = useAppStore()
  const percentage = ref<number>(0)
  const tus = ref<Upload>()
  function initTus(uploadConf: uploadConf) {
    tus.value = new Upload(uploadConf.file, {
      endpoint: uploadConf.endpoint,
      onShouldRetry: () => {
        return false
      },
      headers: {
        authorization: 'Bearer ' + appStore.token
      },
      metadata: {
        filename: uploadConf.file.name,
        filetype: uploadConf.file.type
      },

      onError: (error) => {
        const xError =
          (error as DetailedError)?.originalResponse?.getHeader(
            'X-Tus-Error'
          ) ?? ''
        if (xError.length > 0) {
          const text = encodeURIComponent(xError)
          const errorText = decode(text)
          ToastUtils.error(errorText)
          return
        }
        ToastUtils.error('上传失败，请重新上传')
      },

      onProgress: (bytesUploaded, bytesTotal) => {
        const number = Number(((bytesUploaded / bytesTotal) * 100).toFixed(2))
        if (number <= 99) {
          percentage.value = number
        }
      },
      onAfterResponse: async (req, res) => {
        const result = (await tus.value?.findPreviousUploads()) ?? []
        const item = result?.find(
          (item) =>
            item.metadata.filename === tus.value?.options.metadata?.filename
        )
        const xError = res.getHeader('X-Tus-Error') ?? ''
        if (req.getMethod() === 'PATCH') {
          if (xError.length > 0) {
            const text = encodeURIComponent(xError)
            const error = decode(text)
            ToastUtils.error(error)
            uploadConf.afterError()
            // @ts-ignore
            tus.value?.options.urlStorage?.removeUpload(item.urlStorageKey)
          } else {
            const status = res.getStatus().toString()
            if (status.startsWith('2')) {
              percentage.value = 100
              const data = tus.value?.url
              uploadConf.afterSuccess(data)
              ToastUtils.success('上传成功')
            } else {
              ToastUtils.success('上传失败，请重新上传')
            }
            // @ts-ignore
            tus.value?.options.urlStorage?.removeUpload(item.urlStorageKey)
          }
        }
      }
    })
  }

  function pauseUpload() {
    tus.value?.abort()
  }
  function continueUpload() {
    startOrResumeUpload()
  }

  function askToResumeUpload(previousUploads: any[]) {
    if (previousUploads.length === 0) return null
    const result = previousUploads
      .map((item) => {
        const createTime = item.creationTime
        const now = Date.now()
        const timeDiff = dayjs(now).diff(createTime, 'hour')
        const key = item.urlStorageKey
        if (timeDiff > 0) {
          // 上传时间超过1天未进行续传则重新上传
          tus.value?.options.urlStorage?.removeUpload(key)
          return null
        }
        return item
      })
      .filter(Boolean)
    if (result.length === 0) return null
    return result[0]
  }
  function startOrResumeUpload() {
    tus.value?.findPreviousUploads().then(function (previousUploads) {
      const chosenUpload = askToResumeUpload(previousUploads)
      if (chosenUpload) {
        tus.value?.resumeFromPreviousUpload(chosenUpload)
      }
      tus.value?.start()
    })
  }
  return {
    percentage,
    initTus,
    startOrResumeUpload,
    pauseUpload,
    continueUpload
  }
}
